package com.databias.j15;

import java.awt.Color;
import java.awt.Rectangle;
import java.awt.Graphics2D; //  used for draw function
import java.awt.BasicStroke;
import java.awt.Shape;
import java.awt.geom.AffineTransform;


/**
 * This class can be used to generated a progress bar
 * or bar graph of any height or width.  The bar is
 * constructed by giving the width (or thickness) of the
 * graph and the max size (height or length) of the rectangle.
 * 
 * To use the bargraph, set the max range of values, and if 
 * it is to be vertical.
 * 
 * Then, simply call setValue with your range, and this
 * class will calculate the actual rectangle size
 * 
 * This class is different than other widgets in that it will handle scaling internally.
 * 
 * Unlike the other widgets, the draw command will do the upper-left
 * corner of the graph, which is the top of a bar, or the upper left 
 * of a progress.
 * 
 * This version seems to be better, but breaks others, so it is left here for now.
 * 
 */

public class GBar2 implements GObject {
	
	public final static boolean VERTICAL=true;
	public final static boolean HORIZONTAL=false;
	public final static boolean OUTLINE=true;
	public final static boolean NOOUTLINE=false;
	
	
	private Rectangle myRect;
	private Rectangle myOutline;
	
	// Max dimensions of the outside of the bar
	private int myThickness, myLength; 
	private int mySize=0; // The calculated fill value
	
	private int originx, originy;
	private int maxValue; // The upper limit of expected values
	
	private int currValue; // The value they've last set
	
	private boolean vertical = false; // Is it a bargraph or progress bar
	private boolean outline = true; // should it be outlined
	

	
	/**
	 * Version is to be location agnostic, therefore x,y will be 0,0
	 * @param thickness
	 * @param length
	 * @param vert
	 * @param out
	 */
	public GBar2 (int thickness, int length, boolean vert, boolean out)
	{
		originx=originy=0;
		
		if (thickness <1) thickness=1;
		if (length <1 ) length=1;
		
		myThickness=thickness; // how thick 
		myLength=length; // max size of box
		
		vertical=vert;
		outline=out;
		
		// Create the outer and 'inner' rectangles
		myOutline= new Rectangle(originx, originy, thickness, length);
		myRect = new Rectangle(originx, originy, thickness, 0);
		
	}
	
	
	
	/**
	 * Set the upper bound of values that is > 0
	 * @param max
	 */
	public void setMaxValue(int max)
	{
		if (max <= 0) maxValue=100; // we'll make it %
		
		maxValue=max;
	}
	
	/**
	 * Set the size of our graph by comparing the 
	 * new value to the maximum value.  
	 * 
	 * @param newValue
	 */
	public void setValue(int newValue)
	{
		currValue=newValue;
		
		// It should be a percentage, then multiplied by range of graph

		double floatValue=((double)newValue / (double)maxValue) * (double) myLength;
		mySize=(int) floatValue;
	
		if (mySize > myLength) mySize=myLength;
		
		
		int buffer=2;
		if (!outline) buffer=0;
		
		
		if (vertical)
		{
			// The origin is the lower left corner for
			// my graphing- but in the screen function, it
			// is the upper left.
			// FIXME change back to 'normal' coordinates
			
			myOutline.setBounds(originx, (originy-myLength), myThickness, myLength);
			myRect.setBounds((originx +buffer), (originy-mySize), (myThickness-buffer -1), mySize);
			
		}
		else // progress bar
		{
			System.out.println("Progress bar, width:"+ mySize);
			myOutline.setBounds(originx, (originy-myThickness), myLength, myThickness);
			myRect.setBounds(originx, (originy-myThickness+buffer), mySize, (myThickness-buffer -1));
		}

		
	}
	
	/**
	 * Draw our bar on the referenced screen.  This is done
	 * this way instead of calling the screen function to
	 * do the draw since our graph is actually two rectangles
	 * stacked, with one filled.
	 * 
	 * For a translation, we can either translate the screen (and set it back)
	 * or translate the object.
	 * 
	 * The complexity really depends on what is being drawn.  If it is a simple shape,
	 * then transforming the shape is less complex.
	 * 
	 * If multiple things are drawn (multiple shape, lines, text), then moving
	 * the screen would be a better choice.
	 * 
	 * Here is the code to do each:
	 * 
	 * 	// Translate the object
	 	AffineTransform tx = new AffineTransform();
		tx.translate(barx,bary);
		screen.draw(tx.createTransformedShape(myOutline)); // <- a new shape is created

	 * 
	 * 
	 * Here's the version which moves the screen
	 * 
	    AffineTransform saveXform = screen.getTransform();
	    AffineTransform toCenterAt = new AffineTransform();
	    toCenterAt.translate(barx,bary);
	    screen.transform(toCenterAt);  // <- this moves the screen in the user space
	    <draw on the screen normally>	    
		// Reset it
		screen.setTransform(saveXform);
	 * 
	 * @param screen
	 */
	public void draw(int barx, int bary, Graphics2D screen)
	{
		
		// Translate the location?
		AffineTransform tx = new AffineTransform();
		tx.translate(barx,bary);
		
		// White out our area
		if (outline)
		{
			screen.setColor(Color.WHITE);
			screen.fill(tx.createTransformedShape(myOutline));
		}

		screen.setColor(Color.BLACK);
		screen.setStroke(new BasicStroke(1f));
		
		// Draw our outline
		if (outline)
			//screen.draw(myOutline);
		screen.draw(tx.createTransformedShape(myOutline));
		
		// Draw our graph
		//screen.fill(myRect);
		screen.fill(tx.createTransformedShape(myRect));
	
	}

}
